/*
 * To make this i have used an article i found at this url: 
 * http://www.spheregames.com/download.php?name=sky_pdf
 */

#include "skydome.h"
#include <boost/numeric/ublas/vector.hpp>
#include <iostream>
#include <fstream>

void skydome::draw(){

	glPushAttrib(GL_ENABLE_BIT);
	glShadeModel(GL_SMOOTH);
	glEnable( GL_AUTO_NORMAL );
	glEnable( GL_NORMALIZE );
	glEnable( GL_TEXTURE_2D );

	glColor3f(1.0,1.0,1.0); 
	
	if(grabber->isKeyDown('t'))
		glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
	else
		glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);

	texture1->bind();

	glRotatef(270.0, 1.0, 0.0, 0.0);

	if(grabber->isKeyDown('l')&&shownNumberOfVertices < NumOfVertices){
		printf("Vertices drawn %d\n",shownNumberOfVertices);
		shownNumberOfVertices++;
	}
	if(grabber->isKeyDown('k')&&shownNumberOfVertices > 0){
		printf("Vertices drawn %d\n",shownNumberOfVertices);
		shownNumberOfVertices--;
	}

	glBegin(GL_TRIANGLE_STRIP);

	int i;
	for(i=0; i < shownNumberOfVertices; i++){
		glTexCoord2f(vertices[i+0].u,vertices[i+0].v);
		glVertex3f(vertices[i+0].x, vertices[i+0].y, vertices[i+0].z);
	}
	glEnd();

	glDisable(GL_TEXTURE_2D);

	glPopAttrib();
}

skydome::skydome(void) {
	dtheta = dphi = 30;

	NumOfVertices = (int)((360/dtheta)*(90/dphi)*4);
	
	vertices = new VERTEX[NumOfVertices];
	shownNumberOfVertices = NumOfVertices/2;
	std::cout << "Number of vertices in sphere: " << NumOfVertices << "\n";

	texture1 = new Texture("textures/skypanorama.bmp");

	generateSphereVertices(100.0);
	generateTextureCoordinats(vertices);

}

void skydome::generateSphereVertices(float radius){

	int theta, phi;
	int n = 0,counter=0;
	// this is done in degrees rather then in radians
	
	
	
	for(theta = 0; theta <= 360 - (int)dtheta; theta += (int)dtheta){	
		for(phi = 0; phi <= 90 - (int)dphi; phi += (int)dphi){	
			// phi is the latitude and theta is the longditude
			// dphi and dtheta is the length and hight of the facits created ( must devide phi and theta )
			/* x = r * sin(phi) * cos(theta)
			 * y = r * sin(phi) * sin(theta)
			 * z = r * cos(phi)
			 */
			vertices[n].x = radius * sinf(((float)phi)*DTOR) * cosf(DTOR*((float)theta));
			vertices[n].y = radius * sinf(((float)phi)*DTOR) * sinf(DTOR*((float)theta));
			vertices[n].z = radius * cosf(((float)phi)*DTOR);
			n++;
			
			vertices[n].x = radius * sinf((((float)phi)+dphi)*DTOR) * cosf(((float)theta)*DTOR);
			vertices[n].y = radius * sinf((((float)phi)+dphi)*DTOR) * sinf(((float)theta)*DTOR);
			vertices[n].z = radius * cosf((((float)phi)+dphi)*DTOR);
			n++;

			vertices[n].x = radius * sinf(DTOR*((float)phi)) * cosf(DTOR*(((float)theta)+dtheta));
			vertices[n].y = radius * sinf(DTOR*((float)phi)) * sinf(DTOR*(((float)theta)+dtheta));
			vertices[n].z = radius * cosf(DTOR*((float)phi));
			n++;

			vertices[n].x = radius * sinf((((float)phi)+dphi)*DTOR) * cosf(DTOR*(((float)theta)+dtheta));
			vertices[n].y = radius * sinf((((float)phi)+dphi)*DTOR) * sinf(DTOR*(((float)theta)+dtheta));
			vertices[n].z = radius * cosf((((float)phi)+dphi)*DTOR);
			n++;
			counter++;
		
		}
	}
	std::cout << "counter = " << counter << " | n = " << n << "\n";
	verticesToFile(vertices, "vertexCoordinatsSkydome.txt");
}

void skydome::generateTextureCoordinats(VERTEX * vertices){
	int i;
	// These should be changed later
	float hTile = 1.0, vTile = 1.0;
	float vx,vy,vz,length;
	for(i = 0; i < NumOfVertices; i++){
		vx = vertices[i].x;
		vy = vertices[i].y;
		vz = vertices[i].z;

		length = sqrt(vx*vx + vy*vy + vz*vz);

		vx /= length;
		vy /= length;
		vz /= length;

		vertices[i].u = hTile * (float)( atan2f(vx, vz) / (2.0f * PI) ) + 0.5f;
		vertices[i].v = vTile * (float)( asin(vy) / PI )+ 0.5f;
	}
	textureCoordinatsToFile(vertices,"textureCoordinatsSkydome.txt");
}

void skydome::fixTextureCoordinats(VERTEX * vertices){
		int i;
		for(i=0; i<NumOfVertices - 2; i++){
			// The u coordinat
			if(vertices[i+0].u - vertices[i+1].u > 0.9f)
				vertices[i+1].u += 1.0f;
			if(vertices[i+0].u - vertices[i+2].u > 0.9f)
				vertices[i+2].u += 1.0f;
			if(vertices[i+1].u - vertices[i+0].u > 0.9f)
				vertices[i+0].u += 1.0f;
			if(vertices[i+1].u - vertices[i+2].u > 0.9f)
				vertices[i+2].u += 1.0f;
			if(vertices[i+2].u - vertices[i+0].u > 0.9f)
				vertices[i+0].u += 1.0f;
			if(vertices[i+2].u - vertices[i+1].u > 0.9f)
				vertices[i+1].u += 1.0f;

			// The v coordinat
			if(vertices[i+0].v - vertices[i+1].v > 0.9f)
				vertices[i+1].v += 1.0f;
			if(vertices[i+0].v - vertices[i+2].v > 0.9f)
				vertices[i+2].v += 1.0f;
			if(vertices[i+1].v - vertices[i+0].v > 0.9f)
				vertices[i+0].v += 1.0f;
			if(vertices[i+1].v - vertices[i+2].v > 0.9f)
				vertices[i+2].v += 1.0f;
			if(vertices[i+2].v - vertices[i+0].v > 0.9f)
				vertices[i+0].v += 1.0f;
			if(vertices[i+2].v - vertices[i+1].v > 0.9f)
				vertices[i+1].v += 1.0f;

		}
}

void skydome::verticesToFile(VERTEX * vertices, char * filename){
	std::ofstream file;
	file.open(filename);

	file << "NumOfVertices = " << NumOfVertices << "\n";

	int i;
	for(i=0; i<NumOfVertices; i++){
		file << "Vertex " << i << " = {" << vertices[i].x << ", " << vertices[i].y << ", " << vertices[i].z << "}\n";
	}
	file.close();
}

void skydome::textureCoordinatsToFile(VERTEX * vertices, char * filename){
	std::ofstream file;
	file.open(filename);
	int i;
	float minU = 1.0, maxU = 0.0;
	float minV = 1.0, maxV = 0.0;
	
	for(i=0; i<NumOfVertices; i++){
		if(minU > vertices[i].u)
			minU = vertices[i].u;
		if(maxU < vertices[i].u)
			maxU = vertices[i].u;
		if(minV > vertices[i].v)
			minV = vertices[i].v;
		if(maxV < vertices[i].v)	
			maxV = vertices[i].v;
		file << "Vertex " << i << " = {" << vertices[i].u <<  ", " 
		<< vertices[i].v << "}\n";
	}
	file << "status\n" << "minU=" << minU << " | maxU=" << maxU
					 << "\nminV=" << minV << " | maxV=" << maxV << "\n";
	file.close();
}

void skydome::setGrabber(FPGrabber * g){

	grabber = g;
}